package org.imdm.portal.mdmer;

import java.util.Enumeration;
import java.util.Hashtable;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;

import org.zkoss.zul.ListModelMap;

/**
 * all the MDM members
 * 
 * @author Firebear
 * 
 */
public class Mdmers {
	final private String _MDMERS = "mdmers";
	final private String _MDMER = "mdmer";

	final private String _FIRST_NAME = "firstName";
	final private String _LAST_NAME = "lastName";
	final private String _ESN = "ESN";
	final private String _DEPT = "Dept";

	private String _xmlFileName = "mdmers.xml";
	
	private String _lastErrorMsg = "";

	private ListModelMap mdmerMap = new ListModelMap();

	public synchronized boolean load(String xmlFileName) {
		if ((null != xmlFileName) && ("" != xmlFileName)) {
			this._xmlFileName = xmlFileName;
		}

		return this.load();

	}

	public synchronized boolean save(String xmlFileName) {
		if ((null != xmlFileName) && ("" != xmlFileName)) {
			this._xmlFileName = xmlFileName;
		}

		return this.save();

	}

	public synchronized boolean load() {

		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder;
		try {
			builder = factory.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			this._lastErrorMsg = e.getMessage();
			e.printStackTrace();
			return false;
		}

		Document doc;
		try {
			doc = builder.parse(this._xmlFileName);
		} catch (SAXException e) {
			this._lastErrorMsg = e.getMessage();
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			this._lastErrorMsg = e.getMessage();
			e.printStackTrace();
			return false;
		}

		doc.normalize();
		this.mdmerMap.clear();
		NodeList mdmerList = doc.getElementsByTagName("mdmer");
		for (int idx = 0; idx < mdmerList.getLength(); idx++) {
			try {
				Element elm = (Element) mdmerList.item(idx);
				String firstName = elm.getElementsByTagName(this._FIRST_NAME).item(
						0).getFirstChild().getNodeValue();
				String lastName = elm.getElementsByTagName(this._LAST_NAME).item(0)
						.getFirstChild().getNodeValue();
				String ESN = elm.getElementsByTagName(this._ESN).item(0)
						.getFirstChild().getNodeValue();
				String department = elm.getElementsByTagName(this._DEPT).item(0)
						.getFirstChild().getNodeValue();
	
				Mdmer mdmer = new Mdmer(firstName, lastName, ESN, department);
	
				this.add(mdmer);
			} catch (java.lang.NullPointerException e) {
				this._lastErrorMsg = e.getMessage();
				e.printStackTrace();
				return false;
			}
		}
		return true;

	}

	public synchronized boolean save() {
		Document doc = transform2Document();
		if (null == doc) {
			return false;
		}
		return output2File(doc);
	}

	/**
	 * @param doc
	 * @return
	 * @throws TransformerFactoryConfigurationError
	 */
	private synchronized boolean output2File(Document doc)
			throws TransformerFactoryConfigurationError {
		// output to file
		TransformerFactory tFactory = TransformerFactory.newInstance();
		Transformer transformer;
		try {
			transformer = tFactory.newTransformer();
		} catch (TransformerConfigurationException e) {
			this._lastErrorMsg = e.getMessage();
			e.printStackTrace();
			return false;
		}
		DOMSource source = new DOMSource(doc);
		java.io.File xmlFile = new java.io.File(this._xmlFileName);
		StreamResult result = new StreamResult(xmlFile);
		try {
			transformer.transform(source, result);
		} catch (TransformerException e) {
			this._lastErrorMsg = e.getMessage();
			e.printStackTrace();
			return false;
		}
		
		System.out.println("Contacts have been saved to file " + 
							xmlFile.getAbsolutePath());
		return true;
	}

	/**
	 * @return
	 */
	private synchronized Document transform2Document() {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder;
		try {
			builder = factory.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			this._lastErrorMsg = e.getMessage();
			e.printStackTrace();
			return null;
		}
		Document doc = builder.newDocument();
		Element root = doc.createElement(_MDMERS);
		doc.appendChild(root);

		java.util.Collection<Mdmer> clt = mdmerMap.values();
		for (java.util.Iterator<Mdmer> itr = clt.iterator(); itr.hasNext();) {

			Mdmer mdmer = itr.next();

			Element mdmerNode = doc.createElement(_MDMER);
			Text textSeg;

			textSeg = doc.createTextNode(mdmer.getFirstName());
			Element firstNameNode = doc.createElement(_FIRST_NAME);
			firstNameNode.appendChild(textSeg);
			mdmerNode.appendChild(firstNameNode);

			textSeg = doc.createTextNode(mdmer.getLastName());
			Element lastNameNode = doc.createElement(_LAST_NAME);
			lastNameNode.appendChild(textSeg);
			mdmerNode.appendChild(lastNameNode);

			textSeg = doc.createTextNode(mdmer.getESN());
			Element ESNNode = doc.createElement(_ESN);
			ESNNode.appendChild(textSeg);
			mdmerNode.appendChild(ESNNode);

			textSeg = doc.createTextNode(mdmer.getDepartment());
			Element deptNode = doc.createElement(_DEPT);
			deptNode.appendChild(textSeg);
			mdmerNode.appendChild(deptNode);

			root.appendChild(mdmerNode);
		}
		return doc;
	}

	public synchronized Mdmer remove(String key) {
		return (Mdmer)mdmerMap.remove(key);
	}
	public synchronized boolean add(Mdmer newBee) {
		if (null == newBee) {
			System.out.println("Could not add a null member");
		}
		String key = newBee.getLastName() + "," + newBee.getFirstName();
		Mdmer preOne = (Mdmer) mdmerMap.put(key, newBee);
		if (null == preOne) {
			return true;
		} else {
			this._lastErrorMsg = key + " has been in the list.";
			return false;
		}
	}

	public synchronized ListModelMap getMdmerMap() {
		return mdmerMap;
	}

	public synchronized String getLastErrorMsg() {
		return _lastErrorMsg;
	}

	public synchronized void setLastErrorMsg(String errorMsg) {
		_lastErrorMsg = errorMsg;
	}
}
